:- module(upload_amosdb_cgi, [main/0],
	[pillow, dcg, assertions, regtypes,basicmodes]).

:- use_module(library('pillow/pillow_types')).
:- use_module(library(strings), [write_string/2, get_line/2]).

:- use_module(amos(configuration), [save_data_dir/1]).

:- use_module(portalfiles(web_utils), [generate_box/2]).
:- use_module(portalfiles(standard_page), [standard_page/5]).

main :-
        % Ensure an error page if anything fails
        html_protect(main__2).

main__2 :-
        get_form_input(Info),
        get_form_value(Info, file, File),
	( File = file(_FileName, FileContents),
	    ( upload_contents(FileContents, Result) ->
	        Status = ok(Result)
	    ; Status = error
	    )
        ; Status = input  
        ),
	page(Status, HTML),
	output_html([cgi_reply, HTML]).
	
:- use_module(library(system), [exec/8, working_directory/2]).

upload_contents(Contents, Result) :-
	location(Location),
	instrument_semidet(working_directory(Old, Location),
	                   upload_contents__2(Contents, Result),
			   working_directory(_, Old)).

upload_contents__2(Contents, Result) :-
	exec(tar, ['-vxzf', '-'], In, Out, [], true, _Pid, ErrCode),
	% Send contents
        write_string(In, Contents),
        close(In),
	% Read command output
	get_lines(Out, Lines),
	close(Out),
	% Check command status (error code and output)
	ErrCode = 0,
	check_output(Lines),
	Result = Lines.

get_lines(Stream, Lines) :-
	get_line(Stream, L),
	( L = end_of_file ->
	    Lines = []
	; Lines = [L|Lines0],
	  get_lines(Stream, Lines0)
	).

check_output(Lines) :- % todo: is security too loose here?
	\+ Lines = [].

page(Status, HTML) :-
        generate_box(box_administration, SB1),
        standard_page(all, "Upload the AMOS Database",
	              SB1,
		      Body,
		      HTML),
	page__body(Status, Body).

page__body(ok(Result),
	[
	    p(["The new database has been loaded, please restart ",
	       b("dbserver"), "."]),
	    ResultHTML
	]) :- result_html(Result, ResultHTML).
page__body(error,
	[
	    "There was an error during database upload. ",
	    "Check that the database file is correct or contact the web site administrator."
	]).
page__body(input,
	[
           p(["Please, select the database tarball that you wish to install, ",
              "stop the ", b("dbserver"), " and press the ", b("upload"),
              " button."]), 

	    form([enctype="multipart/form-data", method='POST'],
	    [
		input(file, [name=file, size=50, maxsize=200]),
		input(submit, [value=" Upload "])
	    ])
	]).

result_html(Lines, HTML) :-
	location(Location),
	result_html__2(Lines, LinesHTML),
	HTML = p(["The following files of ", b(Location), " have been uploaded: ", \\, div([style="font-family: monospace; margin:1em"], [LinesHTML])]).

result_html__2([], []).
result_html__2([X|Xs0], [X,\\ |Xs]) :-
	result_html__2(Xs0, Xs).

location(X) :-
	save_data_dir(X0),
	atom_concat(X0, '/database_impl', X).

% ---------------------------------------------------------------------------

% Call a goal Goal, executing instrument code (useful to do and undo
% sideeffects) -- jfran
:- meta_predicate(instrument_semidet(goal, goal, goal)).
instrument_semidet(Enter, Goal, Exit) :-
	Enter, ( Goal -> Exit ; Exit, fail ).



